package com.wpen.unit.core.pool;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 
 * 
 * @author Wang Peng
 * @date 2022-12-04
 */
@Slf4j
public class ExecThreadPool {
    private static ExecThreadPool instance = null;

    public static volatile int totalCount = 0;
    private static ThreadPoolExecutor executorJob = null;

    public synchronized static ExecThreadPool getInstance() {
        if (instance == null) {
            instance = new ExecThreadPool();
        }
        if (executorJob == null || executorJob.isShutdown()) {
            executorJob = new ThreadPoolExecutor(4, 8, 120, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(4),
                    new CustomizableThreadFactory("task-pool-%d"), new ThreadPoolExecutor.CallerRunsPolicy());
        }
        return instance;
    }

    public void execute(Runnable command) {
        executorJob.execute(command);
        int no = ++totalCount;
        printThreadPoolInfo(no);
    }

    private void printThreadPoolInfo(int no) {
        int showLogNum = 50;
        if (executorJob != null && no % showLogNum == 0) {
            log.info("=====>executorJob==>CP>" + executorJob.getCorePoolSize() + " ,PS>" + executorJob.getPoolSize()
                    + " ,AC>" + executorJob.getActiveCount() + " ,QS>" + executorJob.getQueue().size() + " ;TC>"
                    + executorJob.getTaskCount() + " CC>" + executorJob.getCompletedTaskCount());
        }
    }

    public void checkAndWaitFinished() {
        if (executorJob != null && executorJob.getActiveCount() > 0) {
            while (true) {
                try {
                    if (executorJob.getActiveCount() == 0) {
                        break;
                    }
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    public void shutdown() {
        if (executorJob != null && !executorJob.isTerminated()) {
            executorJob.shutdown();
            while (true) {
                try {
                    if (executorJob.awaitTermination(200, TimeUnit.MILLISECONDS)) {
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
}
